/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package co.edu.unal.satacredito.database.dao;

import co.edu.unal.satacredito.database.entity.Machine;
import co.edu.unal.satacredito.database.entity.exceptions.NonexistentEntityException;
import co.edu.unal.satacredito.database.entity.exceptions.NullFieldEntityException;
import co.edu.unal.satacredito.database.entity.exceptions.PreexistingEntityException;
import com.google.code.morphia.Datastore;
import com.google.code.morphia.query.Query;
import com.google.code.morphia.query.UpdateOperations;
import java.util.List;
import org.bson.types.ObjectId;

/**
 *
 * @author migueldiaz
 */
public class MachineMongoDao {

    private Datastore ds = null;

    public MachineMongoDao(Datastore ds) {
        this.ds = ds;
        this.ds.ensureIndexes();
    }

    public Datastore getDatastore() {
        return ds;
    }

    public void create(Machine machine) throws PreexistingEntityException {
        try {
            ds.save(machine);
        } catch (Exception e) {
            throw new PreexistingEntityException("The machine with name "
                    + machine.getMachineName() + " couldn't be created. Already exist.");
        }
    }

    public void update(ObjectId id, Machine newmachine) throws
            NonexistentEntityException, PreexistingEntityException, NullFieldEntityException, Exception {
        try {
            Query q = ds.createQuery(Machine.class).field("_id").equal(id);
            UpdateOperations<Machine> ops = null;
            try {
                ops = ds.createUpdateOperations(Machine.class).set("machineName", newmachine.getMachineName()).set("machineIP", newmachine.getMachineIP()).
                        set("status", newmachine.getStatus()).set("vacant", newmachine.getVacant()).set("typeMachine", newmachine.getTypeMachine());
            } catch (Exception e) {
                throw new NullFieldEntityException("the Machine with id '"
                        + id.toString() + "' have null fields.");
            }
            ds.update(q, ops);
        } catch (Exception e) {
            if (e.getClass().getSimpleName().equals("DuplicateKey")) {
                throw new PreexistingEntityException(e.getMessage());
            } else if (e.getClass().equals(NullFieldEntityException.class)) {
                throw e;
            } else {
                throw new NonexistentEntityException("The machine with id '"
                        + id.toString() + "' couldn't be updated. May no longer exist");
            }
        }
    }

    public void delete(ObjectId id) throws NonexistentEntityException {
        try {
            Query q = ds.createQuery(Machine.class).field("_id").equal(id);
            ds.delete(q);
        } catch (Exception e) {
            throw new NonexistentEntityException("The establishment with the id '"
                    + id.toString() + "' couldn't be deleted. May no longer exist.");
        }
    }

    public List<Machine> findAll() throws NonexistentEntityException {
        try {
            List<Machine> list = ds.find(Machine.class).order("machineName").asList();
            return list;
        } catch (Exception e) {
            throw new NonexistentEntityException("The database "
                    + ds.getMongo().getUsedDatabases()
                    + " at " + ds.getMongo().getAddress()
                    + " don't contain any element of the 'Machine' type ");
        }
    }

    public List<Machine> findByClusterName(String cluster) throws NonexistentEntityException {
        try {
            Query<Machine> q = ds.createQuery(Machine.class).filter("clusterName =", cluster).order("machineName");
            List<Machine> list = q.asList();
            return list;
        } catch (Exception e) {
            throw new NonexistentEntityException("The database "
                    + ds.getMongo().getUsedDatabases()
                    + " at " + ds.getMongo().getAddress()
                    + " don't contain any element asociated with the cluster " + cluster + ".");
        }
    }

    public Machine findByMachineName(String machine) throws NonexistentEntityException {
        try {
            Query q = ds.createQuery(Machine.class).filter("machineName =", machine);
            Machine ma = (Machine) q.get();
            return ma;
        } catch (Exception e) {
            throw new NonexistentEntityException("The database "
                    + ds.getMongo().getUsedDatabases()
                    + " at " + ds.getMongo().getAddress()
                    + " don't contain any element asociated with the machine name " + machine + ".");
        }
    }

    public List<Machine> findByMachineStatus(int status) throws NonexistentEntityException {
        try {
            Query<Machine> q = ds.createQuery(Machine.class).filter("status =", status).order("machineName");
            List<Machine> list = q.asList();
            return list;
        } catch (Exception e) {
            throw new NonexistentEntityException("The database "
                    + ds.getMongo().getUsedDatabases()
                    + " at " + ds.getMongo().getAddress()
                    + " don't contain any machine with the status " + status + ".");
        }
    }

    public List<Machine> findVacant() throws NonexistentEntityException {
        try {
            Query<Machine> q = ds.createQuery(Machine.class).filter("vacant =", 1).order("machineIP");
            List<Machine> list = q.asList();
            return list;
        } catch (Exception e) {
            throw new NonexistentEntityException("The database "
                    + ds.getMongo().getUsedDatabases()
                    + " at " + ds.getMongo().getAddress()
                    + " don't contain any machine vacant.");
        }
    }

    public Machine findByIP(String ip) throws NonexistentEntityException {
        try {
            Query<Machine> q = ds.createQuery(Machine.class).filter("machineIP =", ip);
            Machine ma = (Machine) q.get();
            return ma;
        } catch (Exception e) {
            throw new NonexistentEntityException("The database "
                    + ds.getMongo().getUsedDatabases()
                    + " at " + ds.getMongo().getAddress()
                    + " don't contain any machine with ip '"+ip+"'.");
        }
    }
    
    public List<Machine> findByMachineType(int type) throws NonexistentEntityException{
        try {
            Query<Machine> q = ds.createQuery(Machine.class).filter("typeMachine =", type).order("machineIP");
            List<Machine> list = q.asList();
            return list;
        } catch (Exception e) {
            throw new NonexistentEntityException("The database "
                    + ds.getMongo().getUsedDatabases()
                    + " at " + ds.getMongo().getAddress()
                    + " don't contain any machine with the machine type "+type+".");
        }
        
    }
}
